package ltd.flyweight.liquibasehelper.func.service.impl;

import liquibase.CatalogAndSchema;
import liquibase.LabelExpression;
import liquibase.Liquibase;
import liquibase.change.DatabaseChangeProperties;
import liquibase.database.DatabaseConnection;
import liquibase.database.jvm.JdbcConnection;
import liquibase.dbdoc.ChangeLogWriter;
import liquibase.diff.DiffGeneratorFactory;
import liquibase.diff.DiffResult;
import liquibase.diff.compare.CompareControl;
import liquibase.diff.output.DiffOutputControl;
import liquibase.diff.output.changelog.ChangeGeneratorFactory;
import liquibase.diff.output.changelog.ChangedObjectChangeGenerator;
import liquibase.diff.output.changelog.DiffToChangeLog;
import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.resource.PathResource;
import liquibase.resource.ResourceAccessor;
import liquibase.serializer.LiquibaseSerializable;
import liquibase.serializer.core.yaml.YamlChangeLogSerializer;
import liquibase.snapshot.DatabaseSnapshot;
import liquibase.snapshot.EmptyDatabaseSnapshot;
import liquibase.snapshot.SnapshotControl;
import liquibase.snapshot.SnapshotGeneratorFactory;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Table;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import ltd.flyweight.liquibasehelper.func.service.ILiquibaseHelperService;
import ltd.flyweight.liquibasehelper.module.anchor.service.AnchorTableService;
import ltd.flyweight.liquibasehelper.module.jzgk.service.JzgkSysDictService;
import ltd.flyweight.liquibasehelper.module.jzgk.service.JzgkSysMenuService;
import ltd.flyweight.liquibasehelper.module.jzgk.service.JzgkSysRegionService;
import ltd.flyweight.liquibasehelper.module.zngk.service.ZngkSysDictService;
import ltd.flyweight.liquibasehelper.module.zngk.service.ZngkSysMenuService;
import ltd.flyweight.liquibasehelper.module.zngk.service.ZngkSysRegionService;
import ltd.flyweight.liquibasehelper.utils.PropertiesUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.SystemPropertyUtils;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

@Slf4j
@Service
@RequiredArgsConstructor
public class LiquibaseHelperServiceImpl implements ILiquibaseHelperService {

    private final AnchorTableService anchorTableService;

    private final JzgkSysDictService jzgkSysDictService;
    private final JzgkSysMenuService jzgkSysMenuService;
    private final JzgkSysRegionService jzgkSysRegionService;

    private final ZngkSysDictService zngkSysDictService;
    private final ZngkSysMenuService zngkSysMenuService;
    private final ZngkSysRegionService zngkSysRegionService;

    @SneakyThrows
    @Override
    public void run() {

//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("sys_company_category");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("sys_building_category");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("sys_place_category");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("sys_equipment_category");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("rule_violation");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("rule_violation_item_grade");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("rule_violation_node");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("rule_control_risk_value");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("rule_control_risk_evaluate");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("rule_control_measures");
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("sys_dict_data", "dict_code", 1801500558329888770L);
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("sys_dict_data", "dict_code", 1801500728224366594L);
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("sys_client", 1801501431743365122L);
//
//        bigDataSysDictService.runTaskGenDictTypeAndDataLiquibaseYmlScript("sys_user_type", "1001");
//        bigDataSysDictService.runTaskGenDictTypeAndDataLiquibaseYmlScript("sys_user_type", "1001");
//
//        bigDataSysMenuService.runTaskGenMenuFromBigDataLiquibaseYmlScript(1797556993816326145L, true, true, null, false);
//
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("sensor_type", "100004");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("grade_type", "100005");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("violation_person", "100006");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("is_program_do", "100007");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("violation_dimension", "100008");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("rule_node", "100009");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("layer_type", "100010");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("limit_level", "100011");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("control_risk_value_type", "100012");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("control_risk_evaluate_type", "100013");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("sys_dict_extension_data_type", "1002");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("biz_violation_check_rectify_status", "2000001");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("violation_check_summary", "2000002");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("audit_summary", "2000003");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("rectify_period", "2000004");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("sys_app_type", "1003");
//        zngkSysDictService.runTaskGenDictTypeAndDataFromZngkLiquibaseYmlScript("department_type", "1004");

        // zngkSysRegionService.compare();
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("jzgk-local", "sys_dept", "dept_id",1820276303231381506L);
//        anchorTableService.runTaskGenInitDataLiquibaseYmlScript("jzgk-local", "sys_user", "user_id",1820276699370811393L);
// anchorTableService.runTaskGenInitDataLiquibaseYmlScript("jzgk-local", "sys_app", "id",1802534919409287170L);

        // jzgkSysDictService.full();
        // jzgkSysDictService.runTaskGenDictTypeAndDataLiquibaseYmlScript("biz_violation_check_statistics_status","2000005");
        Properties properties = PropertiesUtils.loadProperties("liquibase.properties");
        Connection connection = DriverManager.getConnection(
                properties.getProperty("url"),
                properties.getProperty("username"),
                properties.getProperty("password")
        );
        Liquibase liquibase = new Liquibase("aaa.xml", new ClassLoaderResourceAccessor(), new JdbcConnection(connection));

        CatalogAndSchema catalogAndSchema = new CatalogAndSchema("management", "public");

        SnapshotControl snapshotControl = new SnapshotControl(liquibase.getDatabase());
        // 获取数据库当前状态的快照
        DatabaseSnapshot snapshot = SnapshotGeneratorFactory
                .getInstance()
                .createSnapshot(
                        catalogAndSchema,
                        liquibase.getDatabase(),
                        snapshotControl
                );
        EmptyDatabaseSnapshot emptyDatabaseSnapshot = new EmptyDatabaseSnapshot(liquibase.getDatabase());
        CompareControl compareControl = new CompareControl();
        DiffResult diffResult = DiffGeneratorFactory.getInstance().compare(snapshot, emptyDatabaseSnapshot, compareControl);

        YamlChangeLogSerializer yamlChangeLogSerializer = new YamlChangeLogSerializer();

        yamlChangeLogSerializer.serialize((LiquibaseSerializable) diffResult,true);
        // 创建YAML序列化器
//        YamlChangeLogSerializer serializer = new YamlChangeLogSerializer();
//        try (OutputStream outputStream = new FileOutputStream("tables.yml")) {
//            serializer.write(diffResult.getChangedObjects().values(), outputStream);
//        }
        // ChangeLogWriter changeLogWriter = new ChangeLogWriter(new ClassLoaderResourceAccessor(), new PathResource("axc.yaml", Path.of("xsax")));

//        try (Writer writer = new FileWriter(changeLogFile)) {
//            ChangeGeneratorFactory changeGeneratorFactory = new CoreChangeGeneratorFactory();
//            changeGeneratorFactory.runGenerators(diffResult, liquibase.getDatabase(), writer, new Contexts(), new LabelExpression());
//        }
//
//        ChangeGeneratorFactory.getInstance().
//        DiffOutputControl diffOutputControl = new DiffOutputControl();
//        DiffToChangeLog diffToChangeLog = new DiffToChangeLog(diffOutputControl);
//        // DatabaseObject databaseObject = new Table(catalogAndSchema.getCatalogName(),catalogAndSchema.getSchemaName(),"sys_dept");
//
//        liquibase.generateChangeLog(catalogAndSchema, diffToChangeLog, new PrintStream("D://abc.xml", Charset.defaultCharset()), Table.class);


        System.out.println("1234\n");
    }

}
